package pers.zb.cloud.service.upms.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.zb.cloud.service.upms.dao.MenuMapper;
import pers.zb.cloud.service.upms.entity.SysMenu;
import pers.zb.cloud.service.upms.enums.MenuShape;
import pers.zb.cloud.service.upms.enums.MenuStatus;
import pers.zb.cloud.service.upms.enums.MenuType;
import pers.zb.cloud.service.upms.service.MenuService;
import pers.zb.cloud.service.upms.util.MenuTreeUtil;
import pers.zb.cloud.service.upms.util.sequence.IdWorker;
import pers.zb.cloud.service.upms.vo.MenuVo;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service("menuServiceImpl")
public class MenuServiceImpl extends BaseServiceImpl<SysMenu> implements MenuService {

    @Autowired
    private MenuMapper sysMenuMapper;

    @Override
    public List<MenuVo> getMenuListByPid(Long pid, int from, String clientId) {
        Example example = new Example(SysMenu.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("pid",pid).andNotEqualTo("status", MenuStatus.DELETE);

        if(!StringUtils.isEmpty(clientId) && !clientId.equals("-1")){ // -1 表示的是最顶层的父节点，也就是我们自定义的分组名称，该节点不是一个应用 。 具体业务代码请看 getClientListTree 方法。
            criteria.andEqualTo("clientId",clientId);
        }

        if(from == 1){//左侧菜单加载
            criteria.andNotEqualTo("status",MenuStatus.DISABLE);
        }
        List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(example);

        List<MenuVo> menuVoList = new ArrayList<>();
        if(sysMenuList == null || sysMenuList.size() <= 0){
            return menuVoList;
        }

        for (SysMenu sysMenu : sysMenuList) {
            MenuVo menuVo = new MenuVo();
            menuVo.setId(sysMenu.getId());
            menuVo.setPid(sysMenu.getPid());
            menuVo.setUrl(sysMenu.getUrl());
            menuVo.setCode(sysMenu.getCode());
            menuVo.setComment(sysMenu.getComment());
            menuVo.setName(sysMenu.getName());
            menuVo.setStatus(sysMenu.getStatus());
            menuVo.setType(sysMenu.getType());
            menuVo.setIcon(sysMenu.getIcon());
            menuVo.setState(sysMenu.getShape().getValue());
            menuVo.setClientId(sysMenu.getClientId());
            menuVoList.add(menuVo);
        }

        //对于拥有子菜单的菜单，递归获取所有层级的子菜单数据
        List<MenuVo> menuTreeList =  MenuTreeUtil.getMenuTreeList(menuVoList,pid);
        return menuTreeList;
    }

    @Override
    public SysMenu getMenuById(Long id) {
        return sysMenuMapper.selectByPrimaryKey(id);
    }

    @Override
    public List<MenuVo> getMenuListByNotItself(Long id,String clientId) {
        Example example = new Example(SysMenu.class);
        example.createCriteria()
                .andNotEqualTo("id",id) //除了自身外
                //.andEqualTo("pid","-1") //获取父菜单
                .andNotEqualTo("status",MenuStatus.DELETE)
                .andNotEqualTo("status",MenuStatus.DISABLE)
                .andEqualTo("clientId",clientId);
        List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(example);

        List<MenuVo> menuVoList = new ArrayList<>();
        if(sysMenuList == null || sysMenuList.size() <= 0){
            return menuVoList;
        }

        for (SysMenu sysMenu : sysMenuList) {
            MenuVo menuVo = new MenuVo();
            menuVo.setId(sysMenu.getId());
            menuVo.setPid(sysMenu.getPid());
            menuVo.setUrl(sysMenu.getUrl());
            menuVo.setCode(sysMenu.getCode());
            menuVo.setComment(sysMenu.getComment());
            menuVo.setName(sysMenu.getName());
            menuVo.setStatus(sysMenu.getStatus());
            menuVo.setType(sysMenu.getType());
            menuVo.setIcon(sysMenu.getIcon());
            menuVo.setState(sysMenu.getShape().getValue());
            menuVoList.add(menuVo);
        }

        //对于拥有子菜单的菜单，递归获取所有层级的子菜单数据
        List<MenuVo> menuTreeList =  MenuTreeUtil.getMenuTreeList(menuVoList);
        return menuTreeList;
    }

    @Override
    @Transactional
    public void updateMenu(SysMenu sysMenu) throws Exception {
        if(sysMenu == null){
            throw new Exception("对象为null");
        }
        //如果选中的菜单下面没有子菜单的话，需要设置state的值为closed，表明是一个父节点（由于前端框架的限制，所以是closed值，固定值）
        boolean haveChildrenMenu = haveChildrenMenu(sysMenu.getPid());
        if(!haveChildrenMenu){
            SysMenu sysMenuParent = getMenuById(sysMenu.getPid());
            sysMenuParent.setShape(MenuShape.CLOSED);
            sysMenuParent.setUpdateTime(new Date());
            sysMenuMapper.updateByPrimaryKeySelective(sysMenuParent);
        }

        SysMenu currentSysMenu = sysMenuMapper.selectByPrimaryKey(sysMenu.getId());//当前更新的菜单

        Example example = new Example(SysMenu.class);
        example.createCriteria().andEqualTo("pid",currentSysMenu.getPid()).andNotEqualTo("status",MenuStatus.DELETE);
        List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(example);//当前更新的菜单的父菜单下面的所有一级子菜单节点
        //当前更新的菜单节点的父节点只有当前更新的权限的这一个子菜单
        if(sysMenuList != null && sysMenuList.size() <= 1){
            SysMenu sysMenuParent = getMenuById(currentSysMenu.getPid());
            sysMenuParent.setShape(MenuShape.OPEN);
            sysMenuParent.setUpdateTime(new Date());
            sysMenuMapper.updateByPrimaryKeySelective(sysMenuParent);
        }
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.updateByPrimaryKeySelective(sysMenu);
    }

    @Override
    @Transactional
    public void deleteMenu(Long[] menuId) throws Exception {
        for (Long id : menuId) {
            SysMenu sysMenu = getMenuById(id);
            if(sysMenu == null){
                throw new Exception("菜单不存在");
            }
            sysMenu.setStatus(MenuStatus.DELETE);
            sysMenu.setUpdateTime(new Date());
            sysMenuMapper.updateByPrimaryKeySelective(sysMenu);

            if(sysMenu.getPid().longValue() != -1L){
                //如果当前菜单的上级菜单的子菜单数量为 1 的话（说明子菜单是当前的菜单），删除当前菜单后，需要更新上级菜单的state为open，说明是没有子菜单的（由于前端框架的限制，所以是open值，固定值）
                Example example = new Example(SysMenu.class);
                example.createCriteria().andEqualTo("pid",sysMenu.getPid()).andNotEqualTo("status",MenuStatus.DELETE);
                List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(example);
                if(sysMenuList != null && sysMenuList.size() <= 1){
                    SysMenu sysMenuParent = getMenuById(sysMenu.getPid());
                    sysMenuParent.setShape(MenuShape.OPEN);
                    sysMenuParent.setUpdateTime(new Date());
                    sysMenuMapper.updateByPrimaryKeySelective(sysMenuParent);
                }
            }
        }
    }

    @Override
    public boolean haveChildrenMenu(Long id) {
        Example example = new Example(SysMenu.class);
        example.createCriteria().andEqualTo("pid",id);
        List<SysMenu> sysMenus = sysMenuMapper.selectByExample(example);
        if(sysMenus != null && sysMenus.size() > 0){
            return true;
        }
        return false;
    }

    @Override
    @Transactional
    public void addMenu(SysMenu sysMenu) throws Exception {
        //如果选中的上级菜单的子菜单数量为 0 的话，需要更新上级菜单的state为closed
        Example example = new Example(SysMenu.class);
        example.createCriteria().andEqualTo("pid",sysMenu.getPid()).andNotEqualTo("status",MenuStatus.DELETE);
        List<SysMenu> sysMenuList = sysMenuMapper.selectByExample(example);
        if(sysMenuList == null || sysMenuList.size() <= 0){
            SysMenu sysMenuParent = getMenuById(sysMenu.getPid());
            sysMenuParent.setShape(MenuShape.CLOSED);
            sysMenuParent.setUpdateTime(new Date());
            sysMenuMapper.updateByPrimaryKeySelective(sysMenuParent);
        }

        sysMenu.setId(IdWorker.id.nextId());
        sysMenu.setCreateTime(new Date());
        sysMenu.setShape(MenuShape.OPEN);
        sysMenu.setType(MenuType.NODE);
        sysMenu.setUpdateTime(new Date());
        sysMenuMapper.insert(sysMenu);
    }
}
